package com.hjx.face.javacv.face;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.DWORD;
import com.sun.jna.platform.win32.WinDef.HMODULE;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.HOOKPROC;
import com.sun.jna.platform.win32.WinUser.MSG;

public class MouseHook implements Runnable{
	
	public static final int WM_MOUSEMOVE = 512;
	private static HHOOK hhk;
	private static LowLevelMouseProc mouseHook;
	final static User32 lib = User32.INSTANCE;
	private boolean [] on_off=null;

	public MouseHook(boolean [] on_off){
		this.on_off = on_off;
	}

	public interface LowLevelMouseProc extends HOOKPROC {
		LRESULT callback(int nCode, WPARAM wParam, MOUSEHOOKSTRUCTEX lParam);
	}
	
	/**
	 * typedef struct {

        	MOUSEHOOKSTRUCT MOUSEHOOKSTRUCT;
    
        	DWORD mouseData;
    
    	} MOUSEHOOKSTRUCTEX
	 * @author HuangJianxiong
	 * 2017年4月20日 上午11:41:25
	 */
	public static class MOUSEHOOKSTRUCTEX extends Structure {
		public MOUSEHOOKSTRUCTEX() {
			super();
		}
		public MOUSEHOOKSTRUCTEX(Pointer p) {
			super(p);
			read();
		}
		
		public static class ByReference extends MOUSEHOOKSTRUCT implements Structure.ByReference {};
		public MOUSEHOOKSTRUCT MOUSEHOOKSTRUCT;
		public DWORD mouseData;
		@Override
		protected List<String> getFieldOrder() {
			return Arrays.asList("MOUSEHOOKSTRUCT","mouseData");
		}
	}
	
	/**
	 * typedef struct {

            POINT pt;
        
            HWND hwnd;
        
            UINT wHitTestCode;
        
            ULONG_PTR dwExtraInfo;
        
        } MOUSEHOOKSTRUCT
	 * @author HuangJianxiong
	 * 2017年4月20日 上午11:41:39
	 */
	public static class MOUSEHOOKSTRUCT extends Structure {
		public static class ByReference extends MOUSEHOOKSTRUCT implements
		Structure.ByReference {
		};
		public User32.POINT pt;
		public int wHitTestCode;
		public User32.ULONG_PTR dwExtraInfo;
		@Override
		protected List<String> getFieldOrder() {
			return Arrays.asList("pt","wHitTestCode","dwExtraInfo");
		}
	}
	/**
	 * 鼠标事件拦截器
	 * @author HuangJianxiong
	 * 2017年4月20日 下午2:24:07
	 */
	public interface MouseHookIntercept{
		/**
		 * 判断鼠标事件是否拦截
		 * @param button
		 * @param x
		 * @param y
		 * @return  true=拦截
		 */
		public boolean check(int button,int x,int y);
	}
	public MouseHookIntercept intercept=null;
	boolean needIntercept=false;
	public void run() {
		HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
		mouseHook = new LowLevelMouseProc() {
			public LRESULT callback(int nCode, WPARAM wParam,
					MOUSEHOOKSTRUCTEX info) {
				
				System.out.println(nCode+"鼠标事件="+wParam+"=x坐标=" + info.MOUSEHOOKSTRUCT.pt.x+ " y坐标=" + info.MOUSEHOOKSTRUCT.pt.y);
				if (intercept!=null) {
					needIntercept=intercept.check(wParam.intValue(),info.MOUSEHOOKSTRUCT.pt.x, info.MOUSEHOOKSTRUCT.pt.y);
				}
				
				long nativeValue = Pointer.nativeValue(info.getPointer());
				if (needIntercept) {
					wParam.setValue(0);
					nativeValue=0;
					return new LRESULT(1);
				}
				return lib.CallNextHookEx(hhk, nCode, wParam, new LPARAM(nativeValue));
			}
		};
		hhk = lib.SetWindowsHookEx(User32.WH_MOUSE_LL, mouseHook, hMod, 0);
		int result;
		MSG msg = new MSG();
		while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
			if (result == -1) {
				System.err.println("error in get message");
				break;
			} else {
				System.err.println("got message");
				lib.TranslateMessage(msg);
				lib.DispatchMessage(msg);
			}
		}
		lib.UnhookWindowsHookEx(hhk);
	}
}
